/**
* @File:w25qxx.h
* @Version:V1.0
* @Author:rudius
* @Brief: SPI Flash W25QXX Driver Interface
* @Logs:
* 	Date		Author		Notes
* 	2025-06-19	rudius		First version
*/

#ifndef __W25QXX_H
#define __W25QXX_H
// <<< Use Configuration Wizard in Context Menu >>>

/* Includes ------------------------------------------------------------------*/
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <rtthread.h>  // 添加RT-Thread头文件
#include "drv_spi.h"  // 用户提供的SPI驱动接口

#ifdef __cplusplus
extern "C" {
#endif

/* Public define -------------------------------------------------------------*/
/* 指令定义 - 参考芯片手册第8节 */
#define W25QXX_CMD_WRITE_ENABLE      0x06
#define W25QXX_CMD_WRITE_DISABLE     0x04
#define W25QXX_CMD_READ_STATUS_REG1  0x05
#define W25QXX_CMD_READ_STATUS_REG2  0x35
#define W25QXX_CMD_READ_STATUS_REG3  0x15
#define W25QXX_CMD_WRITE_STATUS_REG  0x01
#define W25QXX_CMD_PAGE_PROGRAM      0x02
#define W25QXX_CMD_QUAD_PAGE_PROGRAM 0x32
#define W25QXX_CMD_SECTOR_ERASE      0x20
#define W25QXX_CMD_BLOCK_ERASE_32K   0x52
#define W25QXX_CMD_BLOCK_ERASE_64K   0xD8
#define W25QXX_CMD_CHIP_ERASE        0xC7
#define W25QXX_CMD_READ_DATA         0x03
#define W25QXX_CMD_FAST_READ         0x0B
#define W25QXX_CMD_FAST_READ_DUAL    0x3B
#define W25QXX_CMD_FAST_READ_QUAD    0x6B
#define W25QXX_CMD_READ_JEDEC_ID     0x9F
#define W25QXX_CMD_RELEASE_POWERDOWN 0xAB
#define W25QXX_CMD_ENABLE_RESET      0x66
#define W25QXX_CMD_RESET_DEVICE      0x99

/* 状态寄存器位定义 - 参考芯片手册第7.1节 */
#define W25QXX_STATUS_BUSY_BIT      (1 << 0)
#define W25QXX_STATUS_WEL_BIT       (1 << 1)
#define W25QXX_STATUS_QE_BIT         (1 << 1)  // 状态寄存器2的第1位

/* 错误代码 */
#define W25QXX_OK                    0
#define W25QXX_ERR_TIMEOUT          -1
#define W25QXX_ERR_WRITE             -2
#define W25QXX_ERR_ERASE             -3
#define W25QXX_ERR_NOT_READY        -4
#define W25QXX_ERR_INVALID_ARG       -5
#define W25QXX_ERR_MEMORY            -6
#define W25QXX_ERR_NOT_FOUND         -7

/* Public macro --------------------------------------------------------------*/
/* 地址计算宏 */
#define W25QXX_SECTOR_ADDR(sector)  ((sector) * 4096UL)
#define W25QXX_BLOCK_32K_ADDR(block) ((block) * 32768UL)
#define W25QXX_BLOCK_64K_ADDR(block) ((block) * 65536UL)

/* Public typedef ------------------------------------------------------------*/
/**
 * @brief W25QXX设备配置结构
 */
typedef struct {
    struct rt_spi_bus_device *spi_bus;  // SPI总线设备
    rt_base_t cs_pin;                   // 片选引脚
    bool quad_mode;                     // 是否启用Quad模式
    uint32_t capacity;                  // 存储器容量(字节)
    uint32_t sector_count;              // 扇区数量
    uint32_t page_size;                 // 页大小(字节)
    uint32_t max_clock_speed;           // 最大时钟速度(Hz)
} w25qxx_config_t;

/**
 * @brief W25QXX设备句柄
 */
typedef struct {
    w25qxx_config_t config;             // 设备配置
    const char *name;                   // 设备实例名称
    rt_mutex_t lock;                    // 设备操作锁
    uint8_t status_reg1;                // 状态寄存器1缓存
    uint8_t status_reg2;                // 状态寄存器2缓存
    struct rt_slist_node list;          // 设备列表节点 - 添加此行
} w25qxx_device_t;

/* Public function prototypes ------------------------------------------------*/

/**
 * @name 设备管理接口
 * @{
 */

/**
 * @brief 创建并注册W25QXX设备
 * @param name 设备名称
 * @param config 设备配置
 * @return 设备句柄指针，失败返回NULL
 */
w25qxx_device_t *w25qxx_create(const char *name, const w25qxx_config_t *config);

/**
 * @brief 销毁并注销W25QXX设备
 * @param dev 设备句柄
 */
void w25qxx_destroy(w25qxx_device_t *dev);

/**
 * @brief 通过名称查找W25QXX设备
 * @param name 设备名称
 * @return 设备句柄指针，未找到返回NULL
 */
w25qxx_device_t *w25qxx_find(const char *name);

/** @} */

/**
 * @name 设备操作接口
 * @{
 */

/**
 * @brief 初始化W25QXX设备
 * @param dev 设备句柄指针
 * @return int 错误代码 (W25QXX_OK 表示成功)
 */
int w25qxx_init_device(w25qxx_device_t *dev);

/**
 * @brief 读取设备ID
 * @param dev 设备句柄
 * @param manufacturer_id 制造商ID输出
 * @param device_id 设备ID输出
 * @return int 错误代码
 */
int w25qxx_read_id(w25qxx_device_t *dev, uint8_t *manufacturer_id, uint16_t *device_id);

/**
 * @brief 读取状态寄存器
 * @param dev 设备句柄
 * @param reg_num 寄存器号 (1,2,3)
 * @param status 状态值输出
 * @return int 错误代码
 */
int w25qxx_read_status(w25qxx_device_t *dev, uint8_t reg_num, uint8_t *status);

/**
 * @brief 写使能
 * @param dev 设备句柄
 * @return int 错误代码
 */
int w25qxx_write_enable(w25qxx_device_t *dev);

/**
 * @brief 写禁止
 * @param dev 设备句柄
 * @return int 错误代码
 */
int w25qxx_write_disable(w25qxx_device_t *dev);

/**
 * @brief 等待设备空闲
 * @param dev 设备句柄
 * @param timeout_ms 超时时间(ms)
 * @return int 错误代码
 */
int w25qxx_wait_busy(w25qxx_device_t *dev, uint32_t timeout_ms);

/**
 * @brief 擦除扇区
 * @param dev 设备句柄
 * @param sector_addr 扇区地址
 * @return int 错误代码
 */
int w25qxx_erase_sector(w25qxx_device_t *dev, uint32_t sector_addr);

/**
 * @brief 擦除32K块
 * @param dev 设备句柄
 * @param block_addr 块地址
 * @return int 错误代码
 */
int w25qxx_erase_block_32k(w25qxx_device_t *dev, uint32_t block_addr);

/**
 * @brief 擦除64K块
 * @param dev 设备句柄
 * @param block_addr 块地址
 * @return int 错误代码
 */
int w25qxx_erase_block_64k(w25qxx_device_t *dev, uint32_t block_addr);

/**
 * @brief 整片擦除
 * @param dev 设备句柄
 * @return int 错误代码
 */
int w25qxx_erase_chip(w25qxx_device_t *dev);

/**
 * @brief 页编程
 * @param dev 设备句柄
 * @param addr 起始地址
 * @param data 数据指针
 * @param len 数据长度
 * @return int 错误代码
 */
int w25qxx_page_program(w25qxx_device_t *dev, uint32_t addr, const uint8_t *data, size_t len);

/**
 * @brief Quad模式页编程
 * @param dev 设备句柄
 * @param addr 起始地址
 * @param data 数据指针
 * @param len 数据长度
 * @return int 错误代码
 */
int w25qxx_quad_page_program(w25qxx_device_t *dev, uint32_t addr, const uint8_t *data, size_t len);

/**
 * @brief 读取数据
 * @param dev 设备句柄
 * @param addr 起始地址
 * @param data 数据缓冲区
 * @param len 数据长度
 * @return int 错误代码
 */
int w25qxx_read_data(w25qxx_device_t *dev, uint32_t addr, uint8_t *data, size_t len);

/**
 * @brief 快速读取
 * @param dev 设备句柄
 * @param addr 起始地址
 * @param data 数据缓冲区
 * @param len 数据长度
 * @return int 错误代码
 */
int w25qxx_fast_read(w25qxx_device_t *dev, uint32_t addr, uint8_t *data, size_t len);

/**
 * @brief Quad模式读取
 * @param dev 设备句柄
 * @param addr 起始地址
 * @param data 数据缓冲区
 * @param len 数据长度
 * @return int 错误代码
 */
int w25qxx_quad_read(w25qxx_device_t *dev, uint32_t addr, uint8_t *data, size_t len);

/**
 * @brief 软件复位
 * @param dev 设备句柄
 * @return int 错误代码
 */
int w25qxx_reset(w25qxx_device_t *dev);

/** @} */

#ifdef __cplusplus
}
#endif

// <<< end of configuration section >>>
#endif
/*------------------------------end of w25qxx.h---------------------------------*/